package busca;


public class No implements Comparable<Object>  {

	Estado estado;  
	No   pai;    
	int    profundidade = 0;
	// custo de ter gerado o no (todo o caminho)
	int    g = 0; 
	// f = g + h
	int    f = -1; 

	public No(Estado estado, No pai) {
		this.estado = estado;
		this.pai = pai;
		if (pai == null) {
			profundidade = 0;
			g = estado.custo();
		} else {
			profundidade = pai.getProfundidade() + 1;
			g = estado.custo() + pai.g;
		}
	}

	public int getProfundidade() {
		return profundidade;
	}

	public Estado getEstado() {
		return estado;
	}

	public No getPai() {
		return pai;
	}

	/** custo acumulado*/
	public int g() {
		return g;
	}

	/**
	 * Custo total
	 */
	public int f() {
		if (f == -1) {
			f = g + ((Heuristica)estado).h();
		}
		return f;
	}

	/**
	 * arruma a profundidade de um no e de seus pais
	 */
	void setProfundidade() {
		if (pai == null) {
			profundidade = 0;
		} else {
			pai.setProfundidade();
			profundidade = pai.getProfundidade() + 1;
		}
	}


	/**
	 * se dois nos sao iguais
	 */
	public boolean equals(Object o) {
		try {
			No n = (No)o;
			return this.estado.equals(n.estado);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	/** custo (g) como fator de ordenacao */
	public int compareTo(Object obj) {
		try {
			No outro = (No)obj;
			if (g > outro.g) {
				return 1; // sou maior (fica depois na fila)
			} else if (g == outro.g) {
				return 0; //custo igual ao no comparado
			} else {
				return -1; // custo menor do que o do nó comparado
			}
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		return 0; //custo igual a no comparado
	}

	/**
	 *  imprime o caminho 
	 */
	public String retornaCaminho() {
		return retornaCaminho(this);
	}

	public String retornaCaminho(No n) {
		if (n != null) {
			return retornaCaminho(n.pai) + n + "; ";
		}
		return "";
	}

	public String toString() {
		return estado.toString();
	}

}
